from kivy.app import App
from kivy.logger import Logger
from kivy.graphics import Color
from kivy.graphics.vertex_instructions import Rectangle

from math import floor
from threading import Timer, RLock


class TargetViewModel(object):
    """
    The view model for the InitialView class.
    """
    default_color_on = Color(1.0, 1.0, 1.0, 1.0)
    night_color_on = Color(0.5, 0.5, 0.5, 1.0)
    default_background_color = Color(0.0, 0.0, 0.0, 1.0) 

    def __init__(self, view):
        self._view = view
        self._appdata = App.get_running_app().appdata
        self._appdata['target_vm'] = self
        self.target_model = None
        # drawning and undrawning
        self.uptime_seconds = 0
        self.downtime_seconds = 0
        self._drawn = False
        self._drawLock = RLock()
        self._visible = False
        self._draw_timer = None
        self._fg_color = TargetViewModel.default_color_on
        self._bg_color = TargetViewModel.default_background_color
        self._bg_rectancle = Rectangle()
        self._set_before()
        
    def set_fg_bg(self, fg, bg):
        if len(fg) == 4 and len(bg) == 4:
            self._fg_color = Color(*fg)
            self._bg_color = Color(*bg)
            self._set_before()

    def _set_before(self):
        before = self._view.canvas.before
        before.clear() 
        before.add(self._bg_color)
        before.add(self._bg_rectancle)

    @property
    def visible(self):
        return self._visible

    @visible.setter
    def visible(self, value):
        tf = True if value else False
        if self._visible != tf:
            self._visible = tf
            if self._visible:
                self._draw()
            else:
                self._undraw()

    def v_handle_on_size(self, instance, value):
        # instance is the view
        # value is the size
        self._bg_rectancle.size = self._view.size
        if not self._drawn:
            self._undraw()
        else:
            self._draw()

    def _undraw(self):
        with self._drawLock:
            self._none_draw_timer()
            if self._drawn is True:
                self._drawn = False
                self._view.canvas.clear()
                self._view.canvas.ask_update()

    def _none_draw_timer(self):
        if self._draw_timer is not None:
            self._draw_timer.cancel()
        self._draw_timer = None
        
    def _draw(self):
        # center the target
        # first size the target
        if self.target_model is not None and self._visible is True:
            with self._drawLock:
                self.target_model.position_graphics(view_size=self._view.size)
                w, h = self.target_model.size
                # use the empty space to center and middle the target.
                pad_w = floor((self._view.size[0] - w) / 2)
                pad_h = floor((self._view.size[1] - h) / 2)
                padding = min(pad_w, pad_h)
                self.target_model.position_graphics(view_padding=padding)
                graphics = self.target_model.get_graphics()
                # now add the graphics to canvas
                canvas = self._view.canvas
                if self._drawn is True:
                    canvas.clear()
                else:
                    self._drawn = True
                canvas.add(self._fg_color)
                for i in graphics:
                    canvas.add(i)
                canvas.ask_update()
                # undraw
                if self.uptime_seconds > 0:
                    self._draw_timer = Timer(self.uptime_seconds, self._cycle_undraw)
                    self._draw_timer.start()

    def _cycle_undraw(self):
        self._draw_timer = None
        self._undraw()
        self._draw_timer = Timer(self.downtime_seconds, self._cycle_draw)
        self._draw_timer.start()

    def _cycle_draw(self):
        self._draw_timer = None
        self._draw()


